package com.glsc.ngateway.common.api.common.dto;

import com.glsc.ngateway.common.api.common.enums.PageConstant;
import com.glsc.ngateway.common.api.common.utils.GatewayStrUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author xuchang
 */
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel
public class PageQueryParamDto<T> {
    @Nullable
    @ApiModelProperty(value = "搜索条件")
    T param;
    
    @Builder.Default
    @NotNull
    @ApiModelProperty(value = "页码从1开始")
    private Integer pageNo = PageConstant.PageNo;

    @Builder.Default
    @NotNull
    @ApiModelProperty(value = "每页显示条数 默认10")
    private Integer pageSize = PageConstant.PageSize;

    @Builder.Default
    @Nullable
    @ApiModelProperty(value = "排序list， 按list顺序进行排序")
    private List<Sort> sorter = java.util.Collections.EMPTY_LIST;

    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @ApiModel
    public static class Sort {
        public static final String ORDER_ASC = "ascend";

        public static final String ORDER_DESC = "descend";

        @NotNull
        @ApiModelProperty(value = "排序的列， 驼峰命名， 后端转为下划线，与数据库字段对应，前端接口命名必须与数据库字段相对应")
        private String field;
        @NotNull
        @ApiModelProperty(value = "ascend 升序， descend 降序")
        private String order;
    }

    /**
     * 将sort组合
     */
    public Optional<org.springframework.data.domain.Sort> getSort(boolean fieldCamel) {
        if (!CollectionUtils.isEmpty(this.sorter)) {
            List<Sort> sortList = sorter.stream()
                    .filter(Objects::nonNull)
                    .filter(s -> Strings.isNotBlank(s.getField()) && Strings.isNotBlank(s.getOrder()))
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(sortList)) {
                return Optional.of(
                        org.springframework.data.domain.Sort.by(
                                sortList.stream()
                                        .map(s -> new org.springframework.data.domain.Sort.Order(
                                                Sort.ORDER_ASC.equals(s.getOrder()) ?
                                                        org.springframework.data.domain.Sort.Direction.ASC
                                                        : org.springframework.data.domain.Sort.Direction.DESC
                                                , fieldCamel ? s.getField() : GatewayStrUtil.camelCase2SnakeCase(s.getField())))
                                        .collect(Collectors.toList()))
                );
            }
        }
        return Optional.empty();
    }

    public Pageable getPageable() {
        Optional<org.springframework.data.domain.Sort> sort = this.getSort(false);
        return sort.map(orders -> PageRequest.of(this.getPageNo() - 1, this.getPageSize(), orders)).orElseGet(() -> PageRequest.of(this.getPageNo() - 1, this.getPageSize()));
    }

    /**
     * 排序字段以驼峰或者下划线分隔
     * * *
     */
    public Pageable getPageable(boolean fieldCamel) {
        Optional<org.springframework.data.domain.Sort> sort = this.getSort(fieldCamel);
        return sort.map(orders -> PageRequest.of(this.getPageNo() - 1, this.getPageSize(), orders)).orElseGet(() -> PageRequest.of(this.getPageNo() - 1, this.getPageSize()));
    }
}
